<template>
    <view :class="$theme.pageStyle">
        <u-popup v-model="spec.show" mode="bottom" border-radius="14" :closeable="true" :safe-area-inset-bottom="true">
            <!-- Header -->
            <view class="header">
                <!-- Goods Image -->
                <u-image width="180" height="180" mode="aspectFill" border-radius="10"
                    :src="spec.goodsOptionsSpec.image || defaultInfo.image" @click="previewGoodsImage" />
                <!-- Goods Checked Specifcation -->
                <view class="header-content u-skeleton-rect">
                    <view class="flex">
                        <!-- 售价 -->
                        <price class="header-content-price" :content="getSpecPrice(spec.priceKey)" main-size="46rpx"
                            minor-size="32rpx" />
                    </view>

                    <!-- 库存 -->
                    <view class="header-content-label">
                        库存：
                        <text v-if="spec.goodsOptionsSpec.stock == 0">缺货</text>
                        <text v-else>
                            {{ spec.goodsOptionsSpec.stock || defaultInfo.stock }}
                            {{ defaultInfo.unit || '' }}
                        </text>
                    </view>

                    <view class="text-base mt-[10rpx]">
                        <text>{{ skuCheckedText }}</text>
                    </view>
                </view>
            </view>
            <!-- Main -->
            <view class="main">
                <!-- Specifcation -->
                <scroll-view scroll-y="true" class="scroll-spec" v-show="specList.length">
                    <view class="spec" v-for="(specItem, specIndex) in specList" :key="specIndex">
                        <!-- Title -->
                        <view class="spec-title">{{ specItem.name }}</view>
                        <!-- Content -->
                        <view class="spec-content">
                            <view v-for="(optionItem, optionIndex) in specItem.specList" :key="optionIndex" :class="[
                                'spec-item',
                                {
                                    'spec-item--active':
                                        spec.checkedList[specIndex].id == optionItem.id
                                },
                                {
                                    'spec-item--disabled': specDisabeld(optionItem.id)
                                }
                            ]" @click="changeSpecOption(specIndex, optionItem.id)">
                                {{ optionItem.value }}
                            </view>
                        </view>
                    </view>
                </scroll-view>

                <!-- Goods Number -->
                <view class="total" v-if="showGoodsNum">
                    <view class="total-label">数量</view>
                    <u-number-box v-model="spec.goodsTotal" :min="spec.minBuy"
                        @change="handleGoodsNumber($event, spec.goodsOptionsSpec.stock)" />
                </view>

                <!--  -->
                <view class="scroll-spec" v-show="!specList.length"></view>
            </view>

            <!-- operation -->
            <view class="operation">
                <view class="operation-button disabled" v-if="spec.goodsOptionsSpec.stock == 0">
                    缺货
                </view>
                <template v-else>
                    <view v-if="webType!=2" class="operation-button" :class="{
                        disabled: !spec.goodsOptionsSpec.stock
                    }" v-for="(item, index) in buttons" :key="index" :style="[item.style]"
                        @click="onButtonHandle(item.event)">
                        {{ item.text }}
                    </view>
					
					<view v-if="webType==2" class="operation-button" :class="{
					    disabled: !spec.goodsOptionsSpec.stock
					}" v-for="(item, index) in jzbuttons" :key="index" :style="[item.style]"
					    @click="onButtonHandle(item.event)">
					    {{ item.text }}
					</view>
                </template>
            </view>
        </u-popup>
    </view>
</template>

<script lang="ts" setup>
import { reactive, computed, watch, unref, PropType, nextTick } from 'vue'
import { useAppStore } from '@/stores/app'

const appStore = useAppStore()
// 网站类型
const webType = appStore.getWebType

/**
 * @description 商品规格选择Popup弹窗
 * @property {String} mode 商品规格模式 (默认值: normal)
 * @property {Array} specList 规格列表 (必填项)
 * @property {Array} specMap 规格映射表 (必填项)
 * @property {Array} buttons 按钮组 (默认: [{ text: '立即购买', style: {}, event: 'buy' }])
 * @event {Function} [event] 点击按钮 (事件名由按钮组的event提供)
 * @example <goods-spec v-model="show" @buy="handleSubmit" />
 */

const emit = defineEmits(['confirm', 'buttonsHandle', 'change'])

const props = defineProps({
    // 显示状态
    value: {
        type: Boolean,
        default: false
    },
    // 按钮组
    buttons: {
        type: Array as PropType<any[]>,
        default: () => [
            {
                text: '立即购买',
                style: {},
                event: 'buy'
            }
        ]
    },
	jzbuttons: {
	    type: Array as PropType<any[]>,
	    default: () => [
	        {
	            text: '立即下单',
	            style: {},
	            event: 'buy'
	        }
	    ]
	},
    // 规格列表
    specList: {
        type: Array as PropType<any[]>,
        default: () => []
    },
    // 规格映射表
    specMap: {
        type: Array as PropType<any[]>,
        default: () => []
    },
    // 活动的商品规格
    activitySpec: {
        type: Array as PropType<any[]>,
        default: () => []
    },
    // 默认商品信息
    defaultInfo: {
        type: Object,
        default: () => ({})
    },
    // 显示商品数量
    showGoodsNum: {
        type: Boolean,
        default: true
    }
})

const spec = reactive<any>({
    show: false, //
    mapTable: new Map(), // 规格值映射表
    checkedList: [], // 已选择的规格列表
    goodsTotal: 1, // 商品数量
    priceKey: 'price', // 显示价格字段
    goodsOptionsSpec: {}, // 商品已选择的规格
    nullSpec: [], // 当前选择中缺货的规格
	minBuy: 1,
    activitySpec: [] // 活动商品sku
})

const specCheckedIds = computed(() =>
    spec.checkedList
        .map((item: any) => item.id)
        .filter((item: any[]) => item)
        .join(',')
)

const specDisabeld = computed(() => (id: number | string) => {
    try {
        if (!spec.nullSpec || !Array.isArray(spec.nullSpec)) {
            return false
        }
        if (spec.nullSpec.includes(id.toString())) {
            return true
        }
        if (spec.goodsOptionsSpec && spec.goodsOptionsSpec.stock === 0 && spec.goodsOptionsSpec.skuValueIds) {
            const ids = (spec.goodsOptionsSpec.skuValueIds || '').toString().split(',')
            return ids.includes(id.toString())
        }
        return false
    } catch (error) {
        console.log('specDisabeld error', error)
        return false
    }
})

// 活动的商品规格当前选择
const getActivityGoodsSpec: any = computed(() => {
    try {
        const checkedSpec = spec.goodsOptionsSpec || {}
        const activitySpec = props.activitySpec || []
        if (checkedSpec.id && Array.isArray(activitySpec) && activitySpec.length > 0) {
            const temp = activitySpec.find((item: any) => item.skuId == checkedSpec.id)
            if (temp) return temp
        }
        return (Array.isArray(activitySpec) && activitySpec.length >= 1) ? activitySpec[0] : {}
    } catch (error) {
        console.log('getActivityGoodsSpec error', error)
        return {}
    }
})

// 获取当前规格价格
const getSpecPrice = computed(() => {
    return (priceKey: string) => {
        return (
            getActivityGoodsSpec.value[priceKey] ||
            spec.goodsOptionsSpec[priceKey] ||
            props.defaultInfo.price
        )
    }
})

const skuCheckedText = computed(() => {
    try {
        const checkedList = spec.checkedList || []
        const sku_text = checkedList
            .map((item: any) => {
                const { id, name } = item || {}
                return (!id ? name : '')
            })
            .filter(Boolean)
            .join(', ')
        
        const goodsSpec = spec.goodsOptionsSpec || {}
        const stock = goodsSpec.stock || 0
        const skuValueArr = goodsSpec.skuValueArr || ''
        
        if (stock > 0 || sku_text) {
            const prefix = sku_text ? '请选择 ' : '已选择 '
            return `${prefix}${sku_text}${skuValueArr} ${spec.goodsTotal || 1} 件`
        } else {
            return '当前商品规格库存不足'
        }
    } catch (error) {
        console.log('skuCheckedText error', error)
        return '请选择规格'
    }
})

const handleOpen = ({ priceKey = 'price' }: any) => {
    spec.show = true
    spec.priceKey = priceKey
}

const handleClose = () => {
    spec.show = false
}

// 选择规格
const changeSpecOption = (index: number, value: number | string) => {
    try {
        const checkedList = spec.checkedList || []
        if (!checkedList[index]) {
            console.log('changeSpecOption: checkedList index 不存在', index)
            return
        }
        const { id } = checkedList[index]
        
        const specList = props.specList || []
        if (!specList[index] || !Array.isArray(specList[index].specList)) {
            return uni.$u.toast('规格数据有误～')
        }
        
        const curSku = specList[index].specList.find((item: any) => item && item.id == value)
        if (!curSku) {
            return uni.$u.toast('规格数据有误～')
        }
        
        if (id == value) {
            value = ''
        }	
        
        checkedList[index].id = value
        checkedList[index].value = curSku.value || ''
    } catch (error) {
        console.log('changeSpecOption error', error)
        uni.$u.toast('选择规格失败')
    }
}

const handleGoodsNumber = async (event: any, num: number) => {
    if (event.value > num) {
        await nextTick()
        spec.goodsTotal = num		
    }
}

// 点击按钮
const onButtonHandle = (event: string) => {
    try {
        const goodsSpec = spec.goodsOptionsSpec || {}
        const stock = goodsSpec.stock || 0
        
        if (spec.goodsTotal > stock) {
            return uni.$u.toast('超出库存数量')
        }
        
        const checkedList = spec.checkedList || []
        const nullSelect = checkedList.find((item: any) => !item || !item.id)
        if (nullSelect) {
            return uni.$u.toast(`请选择${nullSelect.name || '规格'}`)
        }
        
        handleClose()
        throwSpecEmit('buttonsHandle', event)
    } catch (error) {
        console.log('onButtonHandle error', error)
        uni.$u.toast('操作失败')
    }
}

// 查看商品图片
const previewGoodsImage = () => {
    const image = spec.goodsOptionsSpec.image ?? props.defaultInfo.image
    uni.previewImage({ urls: [image] })
}

// 抛出事件
const throwSpecEmit = (name: string, event: string | 'buttons' | 'change') => {
    try {
        const checkedSpec = spec.goodsOptionsSpec || {}
        emit(name, {
            event: event + 'Handle',
            spec: { ...checkedSpec, number: spec.goodsTotal || 1 },
            activitySpec: getActivityGoodsSpec.value || {}
        })
    } catch (error) {
        console.log('throwSpecEmit error', error)
    }
}

const checkStock = () => {
    try {
        const specMap = props.specMap || []
        if (!Array.isArray(specMap) || specMap.length === 0) {
            spec.nullSpec = []
            return
        }
        
        const nullStock = specMap.filter((item: any) => item && item.stock == 0)
        if (!Array.isArray(nullStock) || nullStock.length === 0) {
            spec.nullSpec = []
            return
        }
        
        const checkedIds = unref(specCheckedIds) || ''
        if (!checkedIds) {
            spec.nullSpec = []
            return
        }
        
        spec.nullSpec = nullStock.reduce((prev: any, item: any) => {
            try {
                if (!item || !item.skuValueIds) return prev
                const idsArr = (item.skuValueIds || '').toString().split(',').filter(Boolean)
                const checkIdsArr = checkedIds.toString().split(',').filter(Boolean)
                const includesIds = idsArr.filter((id: any) => checkedIds.includes(id))
                
                // 全选
                if (item.skuValueIds == checkedIds) {
                    return prev.concat(...checkIdsArr)
                }
                // 剩下一个未选
                const checkedList = spec.checkedList || []
                if (includesIds.length && includesIds.length == checkedList.length - 1) {
                    return prev.concat(idsArr.filter((id: any) => !checkedIds.includes(id)))
                }
            } catch (error) {
                console.log('checkStock reduce error', error)
            }
            return prev
        }, [])
    } catch (error) {
        console.log('checkStock error', error)
        spec.nullSpec = []
    }
}

// 监听规格
watch(
    () => spec.checkedList,
    (value) => {
        try {
            const checkedIds = unref(specCheckedIds) || ''
            if (!checkedIds || !spec.mapTable || typeof spec.mapTable.get !== 'function') {
                spec.goodsOptionsSpec = {}
                return
            }
            
            const selectSepc = spec.mapTable.get(checkedIds)
            checkStock()
            
            if (selectSepc) {
                spec.goodsOptionsSpec = selectSepc || {}
                const minBuy = selectSepc.minBuy || 1
                spec.goodsTotal = minBuy
                spec.minBuy = minBuy
                throwSpecEmit('change', 'change')
            } else {
                spec.goodsOptionsSpec = {}
            }
        } catch (error) {
            console.log('watch checkedList error', error)
            spec.goodsOptionsSpec = {}
        }
    },
    { deep: true }
)

// 初始化规格映射表
watch(
    () => props.specMap,
    (value) => {
        try {
            if (!value || !Array.isArray(value) || value.length === 0) {
                spec.mapTable = new Map()
                spec.checkedList = []
                return
            }
            
            // 配置隐射关系spec_value_ids => self
            spec.mapTable = new Map()
            value.forEach((item: any) => {
                if (item && item.skuValueIds) {
                    spec.mapTable.set(item.skuValueIds, item)
                }
            })
            
            // 拿到最小价格
            const prices = value.map((item: any) => item && item.price ? item.price : Infinity).filter((p: number) => p !== Infinity)
            if (prices.length === 0) {
                spec.checkedList = []
                return
            }
            
            const minPrice: any = Math.min.apply(Math, prices)
            const checkItem: any = value.find((item: any) => item && item.stock && item.price && minPrice == item.price)
            
            const specList = props.specList || []
            if (!Array.isArray(specList) || specList.length === 0) {
                spec.checkedList = []
                return
            }
            
            if (checkItem && checkItem.skuValueIds && checkItem.skuValueArr) {
                const checkItemIds = checkItem.skuValueIds.toString().split(',').filter(Boolean)
                const checkItemArr = checkItem.skuValueArr.toString().split(',').filter(Boolean)
                
                //初始化选中数据
                spec.checkedList = specList.map((item: any, index: number) => {
                    const firstSpec = item && Array.isArray(item.specList) && item.specList[0] ? item.specList[0] : null
                    return {			
                        name: item && item.name ? item.name : '',
                        id: checkItemIds[index] || (firstSpec ? firstSpec.id : ''),
                        value: checkItemArr[index] || (firstSpec ? firstSpec.value : '')			
                    }
                })
            } else {
                // 没有找到合适的规格，使用第一个
                spec.checkedList = specList.map((item: any) => {
                    const firstSpec = item && Array.isArray(item.specList) && item.specList[0] ? item.specList[0] : null
                    return {
                        name: item && item.name ? item.name : '',
                        id: firstSpec ? firstSpec.id : '',
                        value: firstSpec ? firstSpec.value : ''
                    }
                })
            }
        } catch (error) {
            console.log('watch specMap error', error)
            spec.mapTable = new Map()
            spec.checkedList = []
        }
    },
    { immediate: true }
)

defineExpose({
    handleOpen,
    handleClose
})
</script>

<style lang="scss" scoped>
.header {
    display: flex;
    padding: 20rpx;

    &-content {
        flex: 1;
        display: flex;
        flex-direction: column;
        justify-content: center;
        margin-left: 20rpx;

        &-label {
            padding-top: 10rpx;
            font-size: 26rpx;
        }

        &-price {
            margin-bottom: 20rpx;
        }
    }
}

.main {
    padding: 20rpx;
    // border-top: $-solid-border;

    .scroll-spec {
        min-height: 520rpx;
        max-height: 800rpx;
    }

    .spec {
        padding: 10rpx 0;

        &-title {
            font-size: 28rpx;
        }

        &-content {
            display: flex;
            flex-wrap: wrap;
            padding-top: 20rpx;
        }

        &-item {
            display: flex;
            align-items: center;
            justify-content: center;
            min-width: 100rpx;
            box-sizing: border-box;
            padding: 8rpx 25rpx;
            margin: 0 20rpx 20rpx 0;
            border-radius: 60px;
            font-size: 26rpx;
            background-color: #f4f4f4;

            &--active {
                color: $u-type-primary;
                background-color: rgba($color: $u-type-primary, $alpha: 0.1);
                border: 2rpx $u-type-primary solid;
            }

            &--disabled {
                position: relative;

                &::after {
                    content: '缺货';
                    position: absolute;
                    right: -20rpx;
                    top: -24rpx;
                    color: #ffffff;
                    width: 70rpx;
                    height: 36rpx;
                    text-align: center;
                    line-height: 36rpx;
                    font-size: 22rpx;
                    border-radius: 20rpx 20rpx 20rpx 0;
                    background-color: $u-type-primary;
                }
            }
        }
    }

    .total {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 20rpx 0;

        &-label {
            font-size: 28rpx;
        }
    }
}

.operation {
    display: flex;
    justify-content: space-between;
    padding: 10rpx 20rpx;

    &-button {
        flex: 1;
        display: flex;
        justify-content: center;
        align-items: center;
        height: 82rpx;
        border-radius: 60px;
        font-size: 30rpx;
        color: #ffffff;
        background-color: $u-type-primary;

        &:nth-child(n + 2) {
            margin-left: 20rpx;
        }

        &.disabled {
            background-color: #d7d7d7;
        }
    }
}
</style>
